package cn.com.klun.tjy.logic;

import cn.com.klun.tjy.cache.SerConsts;
import cn.com.klun.tjy.common.constant.ComConsts;
import cn.com.klun.tjy.dao.entity.TblAveVolMacdInfo;
import cn.com.klun.tjy.dao.entity.TblStockDayInfos;
import cn.com.klun.tjy.dao.mapper.ser.TblAveVolMacdInfoSerMapper;
import cn.com.klun.tjy.dao.mapper.ser.TblStockDayInfosSerMapper;
import cn.com.klun.tjy.dubbo.bean.TjyParametersVo;
import cn.com.klun.tjy.logic.base.BaseLogics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wangheming
 * @ClassName CalculateBreakM5Logic
 * @Description 突破五日均线
 * @date 2018年03月21日 13:30
 */
@Service
public class CalculateBreakM5Logic implements BaseLogics<TjyParametersVo> {

    private Logger logger = LoggerFactory.getLogger(CalculateBreakM5Logic.class);

    @Resource
    private TblStockDayInfosSerMapper tblStockDayInfosSerMapper;
    @Resource
    private TblAveVolMacdInfoSerMapper tblAveVolMacdInfoSerMapper;

    /**
     * 计算规则描述：
     *  1.股票的股价涨到5日均线的上方收盘
     *  2.突破后几天都沿着5日均线的上方运行
     *  3.盘中突破5日均线而收盘却收在5日均线的下方 不算突破 --（此处没计算）
     *  4.已突破收盘价在5日均线的上方而第二天又跌破5日均线，
     *   收盘在5日均线的下方并连续几日都沿着5日均线的下方运行那就不叫突破，不算突破
     * @param tjyParametersVo
     * @return String
     * @throws Exception
     */
    @Override
    public String exec(TjyParametersVo tjyParametersVo) throws Exception {
        // 1:算出历史分析数据 2：并计算出一个买入和卖出的预测值

        String BaseReturnInfo = "突破五日均线:";
        //取出传入的参数
        String stockCode = tjyParametersVo.getString("stockCode");
        String rowNum = tjyParametersVo.getString("rowNum");
        String trnDate = tjyParametersVo.getString("trnDate");

        // 封装查询条件参数
        Map<String, String> queryListInfo = new HashMap<>();
        queryListInfo.put("rowNum", ComConsts.BREAKM5.rowNum); // 查询的条数
        queryListInfo.put("stoId", stockCode); // 股票编码
        queryListInfo.put("trnDate", trnDate); // 交易日期
        List<TblStockDayInfos> stockDayInfoList = null;
        List<TblAveVolMacdInfo> aveVolMacdInfoList = null;
        try {
            stockDayInfoList = tblStockDayInfosSerMapper.queryStockDayInfoList(queryListInfo);
            if (null == stockDayInfoList || 0 == stockDayInfoList.size()) {
                tjyParametersVo.setResDesc(BaseReturnInfo+"未查询出提供的股票每日信息");
                return SerConsts.VERDICT.ERROR;
            }
            aveVolMacdInfoList = tblAveVolMacdInfoSerMapper.queryStockAVMInfoList(queryListInfo);
            if (null == aveVolMacdInfoList || 0 == aveVolMacdInfoList.size()) {
                tjyParametersVo.setResDesc(BaseReturnInfo+"未查询出提供的股票每日计算信息");
                return SerConsts.VERDICT.ERROR;
            }
        } catch (Exception e) {
            logger.error("CalculateBreakM5Logic 数据库查询异常请检查，异常信息{}", e);
            tjyParametersVo.setResDesc(BaseReturnInfo+"CalculateBreakM5Logic 数据库查询异常请检查");
            return SerConsts.VERDICT.ERROR;
        }

        /* 1.股票的股价涨到5日均线的上方收盘*/
        int rollSize = stockDayInfoList.size();
        int turnNum = -2;  // 记录第一次反转坐标 -2和之后做判断防止第一次出现问题
        int turnCount = 0;  // 记录反转次数
        int nodeType = 0; //记录第一次节点的反转类型
        BigDecimal temp = BigDecimal.ZERO;
        BigDecimal abs = BigDecimal.ZERO;
        BigDecimal sum = BigDecimal.ZERO;

        for (int i = 0; i < rollSize; i++) {
            // 在 temp 赋值之前判断
            if (turnNum == (i-1)) {
                int diff = temp.compareTo(BigDecimal.ZERO); // 判断是跌破还是突破
                if (-1 == diff) {//这是突破点
                    nodeType = ComConsts.NODETYPE.UP;
                }
                if (1 == diff) {//这是跌破点
                    nodeType = ComConsts.NODETYPE.DOWN;
                }
            }
            BigDecimal endPri = stockDayInfoList.get(i).getEndPri();
            BigDecimal m5 = aveVolMacdInfoList.get(i).getM5();
            temp = endPri.subtract(m5);
            sum = sum.add(temp);
            abs = abs.add(temp.abs());
            if (!sum.abs().equals(abs)) {
                if (turnCount == 0) {
                    turnNum = i;
                }
                turnCount++;
                sum = BigDecimal.ZERO; // 清零
                abs = BigDecimal.ZERO; // 清零
            }
        }

        if (turnCount >= ComConsts.BREAKM5.turnCountLimit) {//10天转折2次及以上
            //比较动荡
            tjyParametersVo.setResDesc(BaseReturnInfo+"股票动荡较大保持需要观望");
            return SerConsts.VERDICT.WATCH;
        }
        if(turnNum <= 3 && turnNum != -2){
            if(nodeType ==  ComConsts.NODETYPE.UP){
                tjyParametersVo.setResDesc(BaseReturnInfo+"买入观望");
                return SerConsts.VERDICT.B_WATCH;
            }
            if(nodeType ==  ComConsts.NODETYPE.DOWN){
                tjyParametersVo.setResDesc(BaseReturnInfo+"卖出观望");
                return SerConsts.VERDICT.S_WATCH;
            }
        }
        if(turnNum == -2){//没有出现转折点 --此处不做复杂的判断逻辑 意义不大
            tjyParametersVo.setResDesc(BaseReturnInfo+"股票未出现转折需要观望");
            return SerConsts.VERDICT.WATCH;
        }
        tjyParametersVo.setResDesc(BaseReturnInfo+"未作出判断");
        return SerConsts.VERDICT.OTHER;
    }
}
